// Copyright 2012 Sergio, Raul, Dorival. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// STL
#include <iostream>
#include <cmath>

// GemLab
#include "gemlab.h"

using std::cout;
using std::endl;
using GemLab::Vec_t;
using GemLab::IsEqual;
using GemLab::Array;
using GemLab::Cell;
using GemLab::TRI3;
using GemLab::QUA4;
using GemLab::Geo2gnd;
using GemLab::Geo2nvc;
using GemLab::Geo2natc;
using GemLab::Geo2name;

bool check_intersection(Vec_t const & u0, Vec_t const & du, Cell const * c, Vec_t const & solution)
{
    bool with_err = false;
    Vec_t intersection(u0.rows());
    int nint = GemLab::CellIntersectLocal(u0, du, intersection, c);
    cout << "number of intersections = " << nint << endl;
    cout << "intersection = " << intersection[0] << ", " << intersection[1] << ", " << intersection[2] << endl;
    if (nint == 1) {
        if (IsEqual(intersection, solution)) cout << "[1;32mOK[0m" << endl;
        else
        {
            cout << "[1;31mERROR[0m" << endl;
            with_err = true;
        }
    }
    cout << endl;
    return with_err;
}

int main(int argc, char **argv) try
{
    bool with_err = false;

    GemLab::Mesh m2d(2);
    m2d.SetSize(5, 2);
    m2d.SetVert(0, -1, 3., -1.);
    m2d.SetVert(1, -2, 5.,  0.);
    m2d.SetVert(2, -3, 4.,  2.);
    m2d.SetVert(3, -4, 2.,  4.);
    m2d.SetVert(4, -5, 1.,  1.);
    m2d.SetCell(0, -1, QUA4, Array<int>(0, 1, 2, 4));
    m2d.SetCell(1, -2, TRI3, Array<int>(4, 2, 3));
    m2d.WriteMPY("mesh_enrich02");

    Vec_t u0(2), du(2), sol(2);

    // qua4
    cout << "---------------------- qua4 ----------------------" << endl;
    Cell const * c = m2d.Cells[0];
    u0  << -1.0, -0.2;
    du  <<  2.4,  1.6;
    sol <<  0.8,  1.0;
    check_intersection(u0, du, c, sol);

    du  << 2.0, 1.2;
    sol << 1.0, 1.0;
    check_intersection(u0, du, c, sol);

    du  << 0.9, 0.6;
    sol << 0.0, 0.0;
    check_intersection(u0, du, c, sol);

    u0  << -1.0, -1.0;
    du  <<  2.0,  2.0;
    sol <<  1.0,  1.0;
    check_intersection(u0, du, c, sol);

    u0  <<  1.0,  1.0;
    du  << -2.0, -2.0;
    sol << -1.0, -1.0;
    check_intersection(u0, du, c, sol);

    u0  << -1.0, -1.0;
    du  <<  0.0,  2.0;
    sol << -1.0,  1.0;
    check_intersection(u0, du, c, sol);

    // tri3
    cout << "---------------------- tri3 ----------------------" << endl;
    c = m2d.Cells[1];
    u0  << 0.0, 0.0;
    du  << 0.4, 0.6;
    sol << 0.4, 0.6;
    check_intersection(u0, du, c, sol);

    du  << 1.0, 0.0;
    sol << 1.0, 0.0;
    check_intersection(u0, du, c, sol);

    du  << 0.0, 1.0;
    sol << 0.0, 1.0;
    check_intersection(u0, du, c, sol);

    du  << 0.5, 0.5;
    sol << 0.5, 0.5;
    check_intersection(u0, du, c, sol);

    if (with_err) return 1;
    return 0;
}
GEMLAB_CATCH
